package com.googlecode.bipol.war.session;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// ?? TODO: DELETE THIS ??
public class QxUrlRewriteFilter implements Filter
{
    private ServletContext context;
    private final HashMap<String,File> rewrites = new HashMap<String,File>();

    /**
     *
     * @param config
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig config) throws ServletException
    {
        context = config.getServletContext();

        File   root = new File(context.getRealPath("."));
        String str  = config.getInitParameter("rewrite-root");

        if (str != null) {
            root = new File(str).getAbsoluteFile();
            }

        for (Enumeration<String> e = config.getInitParameterNames(); e.hasMoreElements(); ) {
            String name = e.nextElement();
            if (name.startsWith("rewrite-") && !name.equals("rewrite-root")) {
                String path = config.getInitParameter(name);
                int pos = path.indexOf('=');
                if (pos > 0) {
                    String mapTo = path.substring(pos + 1);
                    path = path.substring(0, pos);
                    File file = new File(root, mapTo);
                    rewrites.put(path, file);
                }
            }
        }
    }

    /**
     *
     */
    @Override
    public void destroy() {
    }

    /**
     *
     * @param _request
     * @param _response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest _request, ServletResponse _response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)_request;
        HttpServletResponse response = (HttpServletResponse)_response;

        // Look for files to process from here
        String uri = request.getRequestURI().substring(request.getContextPath().length());
        for (String path : rewrites.keySet()) {
            if (uri.startsWith(path)) {

                // It's got to match a path (i.e. not part of a path)
                if (path.length() == uri.length() || uri.charAt(path.length()) != '/')
                    continue;

                // Find the file
                File file = new File(rewrites.get(path), uri.substring(path.length()));
                //System.out.println(file.getAbsolutePath());
                if (!file.exists())
                    continue;

                // Check timestamps
                response.setDateHeader("Last-Modified", file.lastModified());
                long lastMod = request.getDateHeader("If-Modified-Since");
                if (lastMod > 0 && Math.abs(file.lastModified() - lastMod) < 1000) {
                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                    return;
                }

                // Send the file
                String mimeType = context.getMimeType(file.getName());
                response.setContentType(mimeType);
                response.setContentLength((int)file.length());

                // Output
                OutputStream os = response.getOutputStream();
                FileInputStream fis = new FileInputStream(file);
                byte[] buffer = new byte[8*1024];
                int len;
                while ((len = fis.read(buffer)) > -1)
                    os.write(buffer, 0, len);
                os.flush();
                os.close();
                fis.close();

                // Done
                return;
            }
        }

        chain.doFilter(request, response);
        return;
    }
}
